<?php

namespace common\extend\plugins;

use Yii;
use yii\db\Exception;
use yii\db\Connection;

/**
 * 提供两种分表方案
 * 集成分表的公共操作和属性
 * Class NumberSub
 * @package common\extend\subTable
 */
trait SubTableTrait
{
    // 分表类型 - 根据记录数分表
    public static string $recordLimit = 'record';
    // 分表类型 - 根据表数量分表
    public static string $tableLimit = 'table';

    // 真实表名，当使用model时，指定一个模板表
    public static string $realTable = '';

    /**
     * 分表前缀，分表表名固定为 分表前缀_0、分表前缀_1、... 依次递增
     * @return string
     */
    public static function subTablePrefix(): string
    {
        $className = basename(get_called_class());
        return strtolower($className);
    }

    /**
     * 分表类型，默认表数量分表
     * @return string
     */
    public static function subLimitType(): string
    {
        return static::$tableLimit;
    }

    /**
     * 记录数量分表-每张表的记录数
     * @return int
     */
    public static function recordLimit(): int
    {
        return 300000;
    }

    /**
     * 表数量分表-表的总数
     * @return int
     */
    public static function tableLimit(): int
    {
        return 10;
    }

    /**
     * 获取真实表名
     * @param null $id
     * @return string
     * @throws Exception
     */
    public static function tableName($id = null): string
    {
        if ($id === null) return static::$realTable;
        return static::tableNameByKey($id);
    }

    /**
     * 获取数据库连接，需要时可重写
     * @return Connection|null
     */
    public static function getDb(): ?Connection
    {
        return Yii::$app->getDb();
    }

    /**
     * 直接设置表名
     * @param string $table
     */
    public static function setTableName(string $table){
        static::$realTable = $table;
    }

    /**
     * 根据分表值设置表名
     * @param $id
     * @throws Exception
     */
    public static function setTableNameByKey($id = null){
        static::$realTable = static::tableNameByKey($id);
    }


    /**
     * 根据索引获取表名
     * @param $index
     * @return string
     */
    public static function tableNameByIndex($index): string
    {
        return static::subTablePrefix().'_'.$index;
    }

    /**
     * 根据标识获取表名
     * @param $id
     * @return string
     * @throws Exception
     */
    public static function tableNameByKey($id = null): string
    {
        return static::tableNameByIndex(static::getTableIndex($id));
    }


    /**
     * 获取分表索引
     * @param $id
     * @return int
     * @throws Exception
     */
    public static function getTableIndex($id = null): int
    {
        if (!is_numeric($id)) {
            throw new Exception('sub table fields key must be number');
        }
        $id = intval($id);
        if ($id < 1) return 0;
        if (static::subLimitType() == self::$recordLimit) {
            $limit = static::recordLimit();
            if ($limit <= 0){
                throw new Exception('sub table recordLimit must gt 0');
            }
            $index = floor($id/$limit);
        } else {
            $limit = static::tableLimit();
            $index = $id % $limit;
        }
        return $index;
    }
}